/**
 * 获取y
 * 映射关系如下:当x值在xStart和xEnd之间,则返回yStart和yEnd之间对应的值
 * xStart------x------xEnd
 * yStart----y----yEnd
 */
export function getY(xStart, xEnd, yStart, yEnd, x){
    if(x <= xStart){
        return yStart
    }
    if(x >= xEnd){
        return yEnd
    }
    
    return yStart + (yEnd - yStart) * (x - xStart) / (xEnd - xStart)
}

export class ScrollAnimation{
    constructor(){
        this._isLog             = false
        this._step              = null
        this._animationArr      = []
        this._fixScrollListener = null
        this._scrollListener    = null
    }
    
    // 打印日志
    _log(...arg){
        if(this._isLog){
            console.log(arg)
        }
    }
    
    // 根据滚动位置更新样式属性,滚轮
    _updateStyles(){
        const wheelPosition = window.scrollY
        
        for(let obj of this._animationArr){
            let dom    = obj.dom
            let styles = obj.styles
            
            if(obj.area){
                let [ xStart, xEnd ] = obj.area
                if(wheelPosition < xStart || wheelPosition > xEnd){
                    continue
                }
            }
            
            for(const prop in styles){
                dom.style[prop] = styles[prop](wheelPosition)
            }
        }
    }
    
    // 是否开启日志
    setLog(isLog){
        this._isLog = isLog
        return this
    }
    
    // 固定滚动的步长,自动吸附
    fix(step){
        if(step <= 0 || !Number.isInteger(step)){
            throw new Error("step必须为>0的整数")
        }
        this._step = step
        
        let scrollTimeout       = null
        this._fixScrollListener = (event) => {
            const direction = event.deltaY > 0 ? "down" : "up"
            if(scrollTimeout){
                clearTimeout(scrollTimeout)
            }
            scrollTimeout = setTimeout(() => {
                const currentPosition = window.scrollY
                let targetScrollTop   = currentPosition
                
                if(direction === "down"){
                    targetScrollTop = Math.ceil(currentPosition / this._step) * this._step
                }
                else{
                    targetScrollTop = Math.floor(currentPosition / this._step) * this._step
                }
                
                window.scrollTo({ top: targetScrollTop, behavior: "smooth" })
            }, 200)
        }
        document.addEventListener("wheel", this._fixScrollListener)
        this._log("滚动吸附", step)
        return this
    }
    
    // 添加滚动动画数组
    add(className, styles, area){
        const domArr = document.querySelectorAll(className)
        
        if(domArr.length > 0){
            for(const dom of domArr){
                this._animationArr.push({
                    dom   : dom,
                    styles: Object.assign({}, styles),
                    area  : area,
                })
            }
            this._log("添加监控:", className)
        }
        else{
            this._log("未找到匹配的DOM元素:", className)
        }
        
        return this
    }
    
    // 毫无意义,仅方便在链式调用中书写注释
    tip(str){
        return this
    }
    
    // 启动:监听滚动变化,并更新属性值
    run(){
        this._updateStyles()
        this._scrollListener = (e) => {
            this._updateStyles()
        }
        window.addEventListener("scroll", this._scrollListener)
        this._log("启动")
    }
    
    // 销毁对象
    dispose(){
        window.removeEventListener("scroll", this._scrollListener)
        document.removeEventListener("wheel", this._fixScrollListener)
        this._animationArr      = []
        this._fixScrollListener = null
        this._log("销毁动画")
    }
}

